﻿using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using System.IO;
using RolePlaying;
using Xna.BaseObjects;
using Microsoft.Xna.Framework;
using DC2010;

namespace Xna.Base
{
    public class TM
    {
        private static Dictionary<string, Texture2D> contentTextures = new Dictionary<string, Texture2D>();
        private static Dictionary<string, AnimatingSprite> contentAnimations = new Dictionary<string, AnimatingSprite>();

        private static Texture2D Cursor = null;

        private static AnimationOverides ao = null;

        public static void Init(ContentManager content, GraphicsDevice gd)
        {
            // Load animation overides
            // In case u want to use faster animations etc...
            ao = new AnimationOverides();
            ao.Load("AnimationOverides.xml");

            Root.I.LoadingStatus = "Loading textures...( Effects )";
            LoadEffects(content);

            Root.I.LoadingStatus = "Loading textures...( Interface )";
            LoadInterface(content);

            Root.I.LoadingStatus = "Loading textures...( Wallset )";
            LoadWallset(content, "Grey_big");

            Root.I.LoadingStatus = "Loading textures...( Characters )";
            LoadCharacters(content);

            Root.I.LoadingStatus = "Loading textures...( Items )";
            LoadItems(gd, content);
        }

        private static void LoadItems(GraphicsDevice gd, ContentManager content)
        {
            AddTexture("Items/IngameItems/Mirror_0",
                LoadTexFromDrive(
                Path.Combine(Environment.CurrentDirectory, "Data", Root.I.GameDirectory, "Gfx/Items/IngameItems/Mirror_0.png".Replace("/", "\\")), gd));

            //    content.Load<Texture2D>("Items/IngameItems/Mirror_0"));
            AddTexture("Items/IngameItems/Mirror_m1",
                content.Load<Texture2D>("Items/IngameItems/Mirror_m1"));
        }

        private static void LoadCharacters(ContentManager content)
        {
            AddTexture("Characters/Plague", content.Load<Texture2D>("Characters/Plague"));

        }

        private static void LoadWallset(ContentManager content, string param)
        {
            AddTexture("WallSets/" + param + "/Ceiling", content.Load<Texture2D>("WallSets/" + param + "/Ceiling"));
            AddTexture("WallSets/" + param + "/Floor", content.Load<Texture2D>("WallSets/" + param + "/Floor"));


            // Alt-center
            AddTexture("WallSets/" + param + "/AltWall_0_m1", content.Load<Texture2D>("WallSets/" + param + "/AltWall_0_m1"));
            AddTexture("WallSets/" + param + "/AltWall_0_m2", content.Load<Texture2D>("WallSets/" + param + "/AltWall_0_m2"));
            AddTexture("WallSets/" + param + "/AltWall_0_m3", content.Load<Texture2D>("WallSets/" + param + "/AltWall_0_m3"));
            AddTexture("WallSets/" + param + "/AltWall_0_m4", content.Load<Texture2D>("WallSets/" + param + "/AltWall_0_m4"));
            /*new*/
            AddTexture("WallSets/" + param + "/AltWall_0_m5", content.Load<Texture2D>("WallSets/" + param + "/AltWall_0_m5"));

            // Alt-1
            AddTexture("WallSets/" + param + "/AltWall_m1_0", content.Load<Texture2D>("WallSets/" + param + "/AltWall_m1_0"));
            AddTexture("WallSets/" + param + "/AltWall_m1_m1", content.Load<Texture2D>("WallSets/" + param + "/AltWall_m1_m1"));
            AddTexture("WallSets/" + param + "/AltWall_m1_m2", content.Load<Texture2D>("WallSets/" + param + "/AltWall_m1_m2"));
            AddTexture("WallSets/" + param + "/AltWall_m1_m3", content.Load<Texture2D>("WallSets/" + param + "/AltWall_m1_m3"));
            /*new*/
            AddTexture("WallSets/" + param + "/AltWall_m1_m4", content.Load<Texture2D>("WallSets/" + param + "/AltWall_m1_m4"));
            /*new*/
            AddTexture("WallSets/" + param + "/AltWall_m1_m5", content.Load<Texture2D>("WallSets/" + param + "/AltWall_m1_m5"));

            // -center
            AddTexture("WallSets/" + param + "/Wall_0_m1", content.Load<Texture2D>("WallSets/" + param + "/Wall_0_m1"));
            AddTexture("WallSets/" + param + "/Wall_0_m2", content.Load<Texture2D>("WallSets/" + param + "/Wall_0_m2"));
            AddTexture("WallSets/" + param + "/Wall_0_m3", content.Load<Texture2D>("WallSets/" + param + "/Wall_0_m3"));
            AddTexture("WallSets/" + param + "/Wall_0_m4", content.Load<Texture2D>("WallSets/" + param + "/Wall_0_m4"));
            /*new*/
            AddTexture("WallSets/" + param + "/Wall_0_m5", content.Load<Texture2D>("WallSets/" + param + "/Wall_0_m5"));


            // -1
            AddTexture("WallSets/" + param + "/Wall_m1_0", content.Load<Texture2D>("WallSets/" + param + "/Wall_m1_0"));
            AddTexture("WallSets/" + param + "/Wall_m1_m1", content.Load<Texture2D>("WallSets/" + param + "/Wall_m1_m1"));
            AddTexture("WallSets/" + param + "/Wall_m1_m2", content.Load<Texture2D>("WallSets/" + param + "/Wall_m1_m2"));
            AddTexture("WallSets/" + param + "/Wall_m1_m3", content.Load<Texture2D>("WallSets/" + param + "/Wall_m1_m3"));
            /*new*/
            AddTexture("WallSets/" + param + "/Wall_m1_m4", content.Load<Texture2D>("WallSets/" + param + "/Wall_m1_m4"));
            /*new*/
            AddTexture("WallSets/" + param + "/Wall_m1_m5", content.Load<Texture2D>("WallSets/" + param + "/Wall_m1_m5"));

            // -2 
            AddTexture("WallSets/" + param + "/Wall_m2_m2", content.Load<Texture2D>("WallSets/" + param + "/Wall_m2_m2"));
            AddTexture("WallSets/" + param + "/Wall_m2_m3", content.Load<Texture2D>("WallSets/" + param + "/Wall_m2_m3"));
            AddTexture("WallSets/" + param + "/Wall_m2_m4", content.Load<Texture2D>("WallSets/" + param + "/Wall_m2_m4"));
            AddTexture("WallSets/" + param + "/Wall_m2_m5", content.Load<Texture2D>("WallSets/" + param + "/Wall_m2_m5"));


            AddTexture("WallSets/" + param + "/AltWall_m2_m2", content.Load<Texture2D>("WallSets/" + param + "/AltWall_m2_m2"));
            AddTexture("WallSets/" + param + "/AltWall_m2_m3", content.Load<Texture2D>("WallSets/" + param + "/AltWall_m2_m3"));
            AddTexture("WallSets/" + param + "/AltWall_m2_m4", content.Load<Texture2D>("WallSets/" + param + "/AltWall_m2_m4"));
            AddTexture("WallSets/" + param + "/AltWall_m2_m5", content.Load<Texture2D>("WallSets/" + param + "/AltWall_m2_m5"));

            // - 3 - new
            AddTexture("WallSets/" + param + "/Wall_m3_m4", content.Load<Texture2D>("WallSets/" + param + "/Wall_m3_m4"));
            AddTexture("WallSets/" + param + "/AltWall_m3_m4", content.Load<Texture2D>("WallSets/" + param + "/AltWall_m3_m4"));
            AddTexture("WallSets/" + param + "/Wall_m3_m5", content.Load<Texture2D>("WallSets/" + param + "/Wall_m3_m5"));
            AddTexture("WallSets/" + param + "/AltWall_m3_m5", content.Load<Texture2D>("WallSets/" + param + "/AltWall_m3_m5"));


        }


        private static void LoadInterface(ContentManager content)
        {
            // Bars
            AddTexture("Interface/Bars/BlueBar", content.Load<Texture2D>("Interface/Bars/BlueBar"));
            AddTexture("Interface/Bars/GreenBar", content.Load<Texture2D>("Interface/Bars/GreenBar"));
            AddTexture("Interface/Bars/RedBar", content.Load<Texture2D>("Interface/Bars/RedBar"));
            AddTexture("Interface/Bars/YellowBar", content.Load<Texture2D>("Interface/Bars/YellowBar"));

            // Quest item
            AddTexture("Interface/Box/BoxAqua", content.Load<Texture2D>("Interface/Box/BoxAqua"));

            //Poisoned item - For example sword with applied poison
            AddTexture("Interface/Box/BoxGreen", content.Load<Texture2D>("Interface/Box/BoxGreen"));
            AddTexture("Interface/Box/BoxLime", content.Load<Texture2D>("Interface/Box/BoxLime"));

            // Applied for cursed items. In moment when item cannot be removed.
            AddTexture("Interface/Box/BoxRed", content.Load<Texture2D>("Interface/Box/BoxRed"));
            AddTexture("Interface/Box/BoxViolet", content.Load<Texture2D>("Interface/Box/BoxViolet"));

            AddTexture("Interface/Cursor", content.Load<Texture2D>("Interface/Cursor"));
            AddTexture("Interface/Action", content.Load<Texture2D>("Interface/Action"));
            AddTexture("Interface/ActionPanel", content.Load<Texture2D>("Interface/ActionPanel"));
            AddTexture("Interface/ActionPanel", content.Load<Texture2D>("Interface/ActionPanel"));
            AddTexture("Interface/Inventory", content.Load<Texture2D>("Interface/Inventory"));
            AddTexture("Interface/OpenChest", content.Load<Texture2D>("Interface/OpenChest"));
            AddTexture("Interface/OpenScroll", content.Load<Texture2D>("Interface/OpenScroll"));
            AddTexture("Interface/Panel", content.Load<Texture2D>("Interface/Panel"));
            AddTexture("Interface/PlayerPanelEmpty", content.Load<Texture2D>("Interface/PlayerPanelEmpty"));
            AddTexture("Interface/PlayerPanelHands", content.Load<Texture2D>("Interface/PlayerPanelHands"));
            AddTexture("Interface/Poisoned", content.Load<Texture2D>("Interface/Poisoned"));
            AddTexture("Interface/RessRein", content.Load<Texture2D>("Interface/RessRein"));
            AddTexture("Interface/Spellsheet1", content.Load<Texture2D>("Interface/Spellsheet1"));
            AddTexture("Interface/Spellsheet2", content.Load<Texture2D>("Interface/Spellsheet2"));
            AddTexture("Interface/Spellsheet3", content.Load<Texture2D>("Interface/Spellsheet3"));
            AddTexture("Interface/Spellsheet4", content.Load<Texture2D>("Interface/Spellsheet4"));
            AddTexture("Interface/StatsPanel", content.Load<Texture2D>("Interface/StatsPanel"));
            AddTexture("Interface/TileSet", content.Load<Texture2D>("Interface/TileSet"));
            AddTexture("Interface/Background", content.Load<Texture2D>("Interface/Background"));


            AddTexture("Interface/WalkingPad", content.Load<Texture2D>("Interface/WalkingPad"));
            AddTexture("Interface/WalkingPad_Down", content.Load<Texture2D>("Interface/WalkingPad_Down"));
            AddTexture("Interface/WalkingPad_Up", content.Load<Texture2D>("Interface/WalkingPad_Up"));
            AddTexture("Interface/WalkingPad_Left", content.Load<Texture2D>("Interface/WalkingPad_Left"));
            AddTexture("Interface/WalkingPad_Right", content.Load<Texture2D>("Interface/WalkingPad_Right"));
            AddTexture("Interface/WalkingPad_TurnLeft", content.Load<Texture2D>("Interface/WalkingPad_TurnLeft"));
            AddTexture("Interface/WalkingPad_TurnRight", content.Load<Texture2D>("Interface/WalkingPad_TurnRight"));
            AddTexture("Interface/WalkingPad_Up", content.Load<Texture2D>("Interface/WalkingPad_Up"));

            AddAnimation("Interface/Cursor", "Interface/Cursor");
        }

        private static void LoadEffects(ContentManager content)
        {
            // textures
            AddTexture("Effects/I_IncreaseStat_ANTIFIRE", content.Load<Texture2D>("Effects/I_IncreaseStat_ANTIFIRE"));
            AddTexture("Effects/I_IncreaseStat_ANTIMAGIC", content.Load<Texture2D>("Effects/I_IncreaseStat_ANTIMAGIC"));
            AddTexture("Effects/I_IncreaseStat_DEX", content.Load<Texture2D>("Effects/I_IncreaseStat_DEX"));
            AddTexture("Effects/I_IncreaseStat_INT", content.Load<Texture2D>("Effects/I_IncreaseStat_INT"));
            AddTexture("Effects/I_IncreaseStat_LCK", content.Load<Texture2D>("Effects/I_IncreaseStat_LCK"));
            AddTexture("Effects/I_IncreaseStat_STR", content.Load<Texture2D>("Effects/I_IncreaseStat_STR"));
            AddTexture("Effects/I_IncreaseStat_VIT", content.Load<Texture2D>("Effects/I_IncreaseStat_VIT"));
            AddTexture("Effects/I_IncreaseStat_WIS", content.Load<Texture2D>("Effects/I_IncreaseStat_WIS"));
            AddTexture("Effects/P_Poison", content.Load<Texture2D>("Effects/P_Poison"));
            AddTexture("Effects/P_RestoreAll", content.Load<Texture2D>("Effects/P_RestoreAll"));

            // corresponding animations.
            AddAnimation("Effects/I_IncreaseStat_ANTIFIRE", "Effects/I_IncreaseStat_ANTIFIRE");
            AddAnimation("Effects/I_IncreaseStat_ANTIMAGIC", "Effects/I_IncreaseStat_ANTIMAGIC");
            AddAnimation("Effects/I_IncreaseStat_DEX", "Effects/I_IncreaseStat_DEX");
            AddAnimation("Effects/I_IncreaseStat_INT", "Effects/I_IncreaseStat_INT");
            AddAnimation("Effects/I_IncreaseStat_LCK", "Effects/I_IncreaseStat_LCK");
            AddAnimation("Effects/I_IncreaseStat_STR", "Effects/I_IncreaseStat_STR");
            AddAnimation("Effects/I_IncreaseStat_VIT", "Effects/I_IncreaseStat_VIT");
            AddAnimation("Effects/I_IncreaseStat_WIS", "Effects/I_IncreaseStat_WIS");
            AddAnimation("Effects/P_Poison", "Effects/P_Poison");
            AddAnimation("Effects/P_RestoreAll", "Effects/P_RestoreAll");
        }

        public static Texture2D LoadTexFromDrive(string filename, GraphicsDevice gd)
        {
            Texture2D tex = null;

            if (File.Exists(filename))
            {
                using (Stream stream = File.OpenRead(filename))
                {
                    tex = Texture2D.FromStream(gd, stream);
                }
            }

            return tex;
        }

        /// <summary>
        /// Update all animations...
        /// </summary>
        /// <param name="gameTime"></param>
        public static void Update(GameTime gameTime)
        {
            foreach (AnimatingSprite a in contentAnimations.Values)
            {
                a.UpdateAnimation((float)gameTime.ElapsedGameTime.TotalSeconds);
            }
        }

        public static Texture2D GetTex(string textureId)
        {
            if (contentTextures.ContainsKey(textureId))
                return contentTextures[textureId];

            return null;
        }

        public static void AddTexture(string Key, Texture2D tex)
        {
            if (!contentTextures.ContainsKey(Key))
                contentTextures.Add(Key, tex);
        }

        public static AnimatingSprite GetAnimation(string animationId)
        {
            if (contentAnimations.ContainsKey(animationId))
                return contentAnimations[animationId];

            return null;
        }

        /// <summary>
        /// This method will create new instance of animation
        /// </summary>
        /// <param name="key">ID of animation in collection</param>
        /// <param name="textureId">Id of texture ill create animation from. This texture must be already loaded!</param>
        public static AnimatingSprite AddAnimation(string key, string textureId)
        {
            Texture2D tex = GetTex(textureId);

            AnimatingSprite an = new AnimatingSprite();
            an.FrameDimensions = Tools.GetFrameDimensions(tex);
            an.FramesPerRow = Tools.GetNumberOfFrames(tex);
            an.SourceOffset = new Vector2(0, 0);
            an.Texture = tex;
            an.TextureId = textureId;

            int StartFrame = 1;
            int EndFrame = Tools.GetNumberOfFrames(tex);
            int Speed = 100;

            //does this little bitch have overide?
            AnimationOveride animO = ao.GetOveride(key);
            if (animO != null)
            {
                an.FrameDimensions = animO.FrameDimensions;
                an.FramesPerRow = animO.FramesPerRow;
                an.SourceOffset = animO.SourceOffset;
                StartFrame = animO.StartFrame;
                EndFrame = animO.EndFrame;
                Speed = animO.Speed;
            }

            an.AddAnimation(
                            new Animation(
                                "Idle",
                                StartFrame,
                                EndFrame,
                                Speed,
                                true)
                );

            an.PlayAnimation(0);

            AddAnimation(key, an);
            return an;
        }

        /// <summary>
        /// This method adds animation to collection. No double entries or animation will not be added!
        /// </summary>
        /// <param name="Key">Key for animation.</param>
        /// <param name="tex">Animation object.</param>
        public static void AddAnimation(string Key, AnimatingSprite tex)
        {
            if (!contentAnimations.ContainsKey(Key))
                contentAnimations.Add(Key, tex);
        }

        /// <summary>
        /// Method will create completly new animation in memory, but based on that old one.
        /// </summary>
        /// <param name="idExisting">Id of existing animation we want to duplicate.</param>
        /// <returns></returns>
        public static AnimatingSprite InstantiateAnimation(string idExisting)
        {
            AnimatingSprite anims = GetAnimation(idExisting);

            if (anims != null)
            {
                //create new ID
                string guid = Guid.NewGuid().ToString();

                //this will create new animation and store it under new Key
                AnimatingSprite aNew = AddAnimation(guid, anims.TextureId);

                return aNew;
            }

            return null;
        }
    }
}